package cn.aaa.service.impl;

import cn.aaa.constants.Constants;
import cn.aaa.mapper.LoginMapper;
import cn.aaa.mapper.PermissionMapper;
import cn.aaa.pojo.domain.Login;
import cn.aaa.pojo.domain.Permission;
import cn.aaa.pojo.domain.dto.LoginDto;
import cn.aaa.pojo.domain.vo.LoginSuccessVo;
import cn.aaa.service.ILoginService;
import cn.aaa.template.WechatLoginTemplate;
import cn.aaa.utils.AssertUtil;
import cn.dev33.satoken.stp.SaLoginConfig;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 登录表 服务实现类
 * </p>
 *
 * @author axy
 * @since 2025-03-28
 */
@Service
public class LoginServiceImpl extends ServiceImpl<LoginMapper, Login> implements ILoginService {
    @Autowired
    private WechatLoginTemplate wechatLoginTemplate;
    
    @Autowired
    private RedisTemplate<String ,Object> redisTemplate;
    @Autowired
    private LoginMapper loginMapper;
    
    @Autowired
    private PermissionMapper permissionMapper;
    
    @Override
    public LoginSuccessVo login(LoginDto dto) {
        //1. 用户采用微信登录，后台拿到微信OpenID
        String code = dto.getCode();
        String openId = wechatLoginTemplate.getOpenId(code).getOpenid();
        //2. 根据OpenId和type查询Login对象，为空则提示注册
        AssertUtil.isNotEmpty(openId,"微信ID不可为空");
        Login one = super.getOne(new QueryWrapper<Login>().lambda()
                .eq(Login::getOpenId, openId)
                .eq(Login::getType, dto.getType()));
        AssertUtil.isNotNull(one, "请先注册");
        //3. 调用：StpUtil.login(login.getId()) 执行登录
        this.saTokenLogin(one);
        //4. 封装用户信息如：头像，昵称等返回给前端
        LoginSuccessVo loginVo = new LoginSuccessVo();
        loginVo.setAvatar(one.getAvatar());
        loginVo.setPhone(one.getPhone());
        loginVo.setNickName(one.getNickName());
        loginVo.setId(one.getId());
        //5. 调用：StpUtil.getTokenInfo() 拿到Token，和用户信息一起，返回给前端
        String token = StpUtil.getTokenInfo().tokenValue;
        loginVo.setToken(token);
        
        //存储用户角色和权限信息到Redis中
        //查询用户角色
        List<String> loginRole = loginMapper.getLoginRole(one.getId());
        //查询用户权限
        List<String> loginPermissions = loginMapper.getLoginPermissions(one.getId());
        redisTemplate.opsForValue().set(Constants.redis.USER_ROLE+one.getId().toString(), loginRole);
        redisTemplate.opsForValue().set(Constants.redis.USER_PERMISSION+one.getId().toString(), loginPermissions);
        return loginVo;
    }
    //执行SaToken登录逻辑
    public SaTokenInfo saTokenLogin(Login login){
        StpUtil.login(login.getId(), SaLoginConfig
                //根据需要封装扩展参数
                .setExtra("username", login.getUsername())
                .setExtra("type", login.getType())
                .setExtra("avatar", login.getAvatar())
                .setExtra("admin", login.getAdmin())
                .setExtra("nickName", login.getNickName())
                .setExtra("phone", login.getPhone())
                //加载权限
                .setExtra("permissions", StpUtil.getPermissionList(login.getId()))
                .setExtra("roles", StpUtil.getRoleList(login.getId()))
                .setExtra("openId", login.getOpenId()));
        return StpUtil.getTokenInfo();
    }
}
